﻿using System.Buffers;
using SuperSocket.ProtoBase;

namespace Xph.Sag.Kernel;

/// <summary>
/// XPH通用帧格式
/// </summary>
public class XphPackage : IKeyedPackageInfo<byte>
{
    /// <summary>
    /// 地址
    /// </summary>
    public byte Address { get; set; }
    /// <summary>
    /// 读(0x03)
    /// 写(0x10)操作码 2 选 1
    /// </summary>
    public byte Action { get; set; }
    /// <summary>
    /// 操作码
    /// </summary>
    public byte Key { get; set; }
    /// <summary>
    /// 数据区长度
    /// </summary>
    public int Length { get; set; }
    /// <summary>
    /// 实际数据
    /// </summary>
    public byte[]? Body { get; set; }
    /// <summary>
    /// 小端
    /// </summary>
    public byte[] Crc16 { get; set; } = new byte[2];
}




/// <summary>
/// 新普惠Modbus数据解码器
/// </summary>
public class XphDecoder : IPackageDecoder<XphPackage>
{
    public XphPackage Decode(ref ReadOnlySequence<byte> buffer, object context)
    {
        var reader = new SequenceReader<byte>(buffer);
        
        var pack = new XphPackage();
        reader.TryRead(out byte address);
        reader.TryRead(out byte key);

        // 获取设备地址协议与其他modbus协议不同，需要额外处理，前两字节 0x00,0x20为固定值
        if (address == 0x00 && key == 0x20) 
        {
            reader.TryRead(out address); //请求设备地址时，第三字节为设备实际地址
            pack.Address = address;
            pack.Key = key;
            return pack;
        }

        reader.TryRead(out byte length);
        var data = reader.Sequence.Slice(3, length); //跳过address,action,length三字节
        pack.Address = address;
        pack.Key = key;
        pack.Length = length;
        pack.Body = new byte[data.Length];
        Array.Copy(data.ToArray(), 0, pack.Body, 0, data.Length);
        return pack;
    }
}